package cn.sharp.bbs.service.impl;

import cn.sharp.bbs.controller.msg.MsgType;
import cn.sharp.bbs.dao.gen.CommentMapper;
import cn.sharp.bbs.dao.gen.MessageMapper;
import cn.sharp.bbs.dao.gen.PostMapper;
import cn.sharp.bbs.dao.gen.ReportMapper;
import cn.sharp.bbs.dao.msg.MsgDao;
import cn.sharp.bbs.entity.DO.Message;
import cn.sharp.bbs.entity.DO.Report;
import cn.sharp.bbs.event.*;
import cn.sharp.bbs.service.MsgPushService;
import cn.sharp.bbs.service.SSEService;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author zhao yu
 */
@Service
@Transactional
public class MsgPushServiceImpl implements MsgPushService {

    @Resource
    private SSEService sseService;

    @Resource
    private MessageMapper messageMapper;

    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    @Resource
    private MsgDao msgDao;

    @Override
    @EventListener
    public void commentNotify(CommentEvent commentEvent) {
        Long author = msgDao.getAuthorIdByComment(commentEvent.getKey());
        messageMapper.insert(new Message(null,
                author,
                commentEvent.getKey(),
                MsgType.COMMENT, 0));
        sseService.push(author, MsgType.COMMENT);
        List<Long> followUser =  msgDao.getFollowUserIdByComment(commentEvent.getKey());
        for (Long user : followUser) {
            messageMapper.insert(new Message(null,
                    user,
                    commentEvent.getKey(),
                    MsgType.COMMENT_FOLLOW, 0));
            sseService.push(user, MsgType.COMMENT_FOLLOW);
        }
    }

    @Override
    @EventListener
    public void replyNotify(ReplyEvent replyEvent) {
        Long author = msgDao.getAuthorIdByComment(replyEvent.getKey());
        messageMapper.insert(new Message(null,
                author,
                replyEvent.getKey(),
                MsgType.COMMENT, 0));
        sseService.push(author, MsgType.COMMENT);

        Long commenter = msgDao.getCommenterIdByComment(replyEvent.getKey());
        messageMapper.insert(new Message(null,
                author,
                replyEvent.getKey(),
                MsgType.REPLY, 0));
        sseService.push(commenter, MsgType.REPLY);

        List<Long> followUser =  msgDao.getFollowUserIdByComment(replyEvent.getKey());
        for (Long user : followUser) {
            messageMapper.insert(new Message(null,
                    user,
                    replyEvent.getKey(),
                    MsgType.REPLY_FOLLOW, 0));
            sseService.push(user, MsgType.REPLY_FOLLOW);
        }
    }

    @Override
    @EventListener
    public void commentLikeNotify(CommentLikeEvent commentLikeEvent) {
        Long userId = msgDao.getUserIdByCommentLike(commentLikeEvent.getKey());
        messageMapper.insert(new Message(null,
                userId,
                commentLikeEvent.getKey(),
                MsgType.COMMENT_LIKE, 0));
        sseService.push(userId, MsgType.COMMENT_LIKE);
    }

    @Override
    @EventListener
    public void postLikeNotify(PostLikeEvent postLikeEvent) {
        Long userId = msgDao.getUserIdByPostLike(postLikeEvent.getKey());
        messageMapper.insert(new Message(null,
                userId,
                postLikeEvent.getKey(),
                MsgType.POST_LIKE, 0));
        sseService.push(userId, MsgType.POST_LIKE);
    }

    @Override
    @EventListener
    public void postCheckNotify(PostCheckEvent postCheckEvent) {
        Long userId = msgDao.getUserIdByPostVersion(postCheckEvent.getKey());
        messageMapper.insert(new Message(null,
                userId,
                postCheckEvent.getKey(),
                MsgType.POST_CHECK, 0));
        sseService.push(userId, MsgType.POST_CHECK);
    }

    @Override
    @EventListener
    public void collectNotify(CollectEvent collectEvent) {
        Long userId = msgDao.getUserIdByCollect(collectEvent.getKey());
        messageMapper.insert(new Message(null,
                userId,
                collectEvent.getKey(),
                MsgType.COLLECT, 0));
        sseService.push(userId, MsgType.COLLECT);
    }

    @Override
    @EventListener
    public void followNotify(FollowEvent followEvent) {
        Long userId = msgDao.getUserIdByFollow(followEvent.getKey());
        messageMapper.insert(new Message(null,
                userId,
                followEvent.getKey(),
                MsgType.FOLLOW, 0));
        sseService.push(userId, MsgType.FOLLOW);
    }

    @Resource
    private ReportMapper reportMapper;

    @Resource
    private PostMapper postMapper;
    @Resource
    private CommentMapper commentMapper;

    @Override
    @EventListener
    public void reportPassNotify(ReportPassEvent reportPassEvent) {
        Report report = reportMapper.selectByPrimaryKey(reportPassEvent.getKey());
        messageMapper.insert(new Message(null,
                report.getsUserId(),
                report.getId(),
                MsgType.REPORT_SUCCESS,
                0));
        Long beReported = null;
        switch (report.getType()){
            case 0:
                beReported = postMapper.selectByPrimaryKey(report.getTarget()).getUserId();
                break;
            case 1:
                beReported = commentMapper.selectByPrimaryKey(report.getTarget()).getUserId();
                break;
            case 2:
                beReported = report.getTarget();
                break;
        }
        messageMapper.insert(new Message(null,
                beReported,
                report.getId(),
                MsgType.REPORTED,
                0));
        sseService.push(report.getsUserId(), MsgType.REPORT_SUCCESS);
        sseService.push(report.getTarget(), MsgType.REPORTED);
    }

    @Override
    @EventListener
    public void reportRejectNotify(ReportRejectEvent reportRejectEvent) {
        Report report = reportMapper.selectByPrimaryKey(reportRejectEvent.getKey());
        messageMapper.insert(new Message(null,
                report.getsUserId(),
                report.getId(),
                MsgType.REPORT_FAIL,
                0));
        sseService.push(report.getsUserId(), MsgType.REPORT_FAIL);
    }

    /**
     * 对收到私信的用户发送通知
     * @param letterEvent 私信事件
     */
    @Override
    @EventListener
    public void letterNotify(LetterEvent letterEvent) {
        messageMapper.insert(new Message(null,
                letterEvent.getUserId(),
                letterEvent.getChatRoom(),
                MsgType.LETTER, 0));
        sseService.push(letterEvent.getUserId(), MsgType.LETTER);
    }

    @Override
    public void testPush(Long id) {
        applicationEventPublisher.publishEvent(new PostLikeEvent(this, id));
    }
}
